package de.slothsoft.test.treetable2;

import java.awt.Component;
import java.awt.Point;

import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.tree.DefaultTreeCellRenderer;

public class JTreeTable extends JTable {

	private static final long serialVersionUID = 771986L;

	// TODO: change column model / renderer

	@Override
	public AccessibleContext getAccessibleContext() {
		if (this.accessibleContext == null || !(this.accessibleContext instanceof AccessibleJTreeTable)) {
			this.accessibleContext = new AccessibleJTreeTable();
		}
		return this.accessibleContext;
	}

	public void setDefaultRenderer(Class<?> columnClass, TreeTableCellRenderer renderer) {
		super.setDefaultRenderer(columnClass, renderer);
	}

	@Override
	public void setDefaultRenderer(Class<?> columnClass, TableCellRenderer renderer) {
		setDefaultRenderer(columnClass, (TreeTableCellRenderer) renderer);
	}

	@SuppressWarnings("serial")
	protected class AccessibleJTreeTable extends AccessibleJTable {

		private final DummyTreeTableCellRenderer dummyRenderer = new DummyTreeTableCellRenderer();

		@Override
		public Accessible getAccessibleAt(Point p) {
			int column = columnAtPoint(p);
			int row = rowAtPoint(p);

			if (column != -1 && row != -1) {
				TableColumn aColumn = getColumnModel().getColumn(column);
				TableCellRenderer renderer = aColumn.getCellRenderer();
				if (renderer == null) {
					Class<?> columnClass = getColumnClass(column);
					renderer = getDefaultRenderer(columnClass);
				}
				getRendererComponent(renderer, row, column);
				return new AccessibleJTableCell(JTreeTable.this, row, column, getAccessibleIndexAt(row, column));
			}
			return null;
		}

		@Override
		public Accessible getAccessibleChild(int i) {
			if (i < 0 || i >= getAccessibleChildrenCount()) {
				return null;
			}
			// children increase across, and then down, for tables
			// (arbitrary decision)
			int column = getAccessibleColumnAtIndex(i);
			int row = getAccessibleRowAtIndex(i);

			TableColumn aColumn = getColumnModel().getColumn(column);
			TableCellRenderer renderer = aColumn.getCellRenderer();
			if (renderer == null) {
				Class<?> columnClass = getColumnClass(column);
				renderer = getDefaultRenderer(columnClass);
			}
			getRendererComponent(renderer, row, column);
			return new AccessibleJTableCell(JTreeTable.this, row, column, getAccessibleIndexAt(row, column));
		}

		private Component getRendererComponent(TableCellRenderer renderer, int row, int column) {
			TreeTableCellRenderer treeTableCellRenderer;
			if (renderer instanceof TreeTableCellRenderer) {
				treeTableCellRenderer = (TreeTableCellRenderer) renderer;
			} else {
				this.dummyRenderer.init(renderer);
				treeTableCellRenderer = this.dummyRenderer;
			}
			return getRendererComponent(treeTableCellRenderer, row, column);
		}

		private Component getRendererComponent(TreeTableCellRenderer renderer, int row, int column) {
			if (column == 0) {
				return renderer.getTreeCellRendererComponent(null, false, false, false, false, row, false);
			}
			return renderer.getTableCellRendererComponent(JTreeTable.this, null, false, false, row, column);
		}
	}

	private class DummyTreeTableCellRenderer extends DefaultTreeCellRenderer implements TreeTableCellRenderer {

		private static final long serialVersionUID = 1L;

		private TableCellRenderer renderer;

		public void init(TableCellRenderer renderer) {
			this.renderer = renderer;
		}

		@Override
		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
				boolean hasFocus, int row, int column) {
			return this.renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
		}

	}
}
